gusucode.com > VC 达内MFC例子集源码-源码程序 > VC 达内MFC例子集源码-源码程序/code/20101227/day01.txt

    MFC应用程序编程

一 MFC的发展

  VC 1.0->VC 5.0->VC 6.0->VC2008 SP1)->VS2010
  
二 MFC基础

  1 MFC 微软基础类库 
    采用类的方式,将Win32 API等进行封装,
    形成的库.
    
  2 MFC相关的头文件
  	afx.h   (application framework, X)
  	afxwin.h  (类似于windows.h)
  	afxext.h  MFC扩展头文件
  	...
  	
三 MFC应用程序

  1 MFC的控制台程序
    1.1 包含afx系列的头文件
    1.2 CWinApp theApp - MFC的应用程序类
          封装了应用程序的启动过程.
    1.3 AfxWinInit MFC初始化函数 
          将应用程序的信息初始化.
  2 MFC的动态库和静态库
    2.1 静态库 - 增加了MFC的支持
    2.2 动态库
      2.2.1 MFC规则DLL
        2.2.1.1 使用MFC静态库的规则DLL
        2.2.1.2 使用MFC动态库的规则DLL
      2.2.2 MFC扩展DLL
    2.3 不同
       2.3.1 MFC相关的afx头文件
       2.3.2 包含一个继承CWinApp类, 并且
          声明了该类的全局变量.
  3 MFC应用程序
    3.1 单文档视图应用程序
      3.1.1 包含一个继承CWinApp类
      3.1.2 CMainFrame类
      3.1.3 CView的一个子类
      3.1.4 CDocument的一个子类
    3.2 多文档视图应用程序
      3.2.1 包含一个继承CWinApp类
      3.2.2 CMainFrame类
      3.2.3 CView的一个子类
      3.2.4 CDocument的一个子类
      3.2.5 CChildFrame 子框架窗口
    3.3 对话框应用程序
      3.3.1 包含一个继承CWinApp类
      3.3.2 对话框类
      
四 MFC中的类

  1 CObject类
    MFC类的基础,大部分MFC类都是它的子类.
    CObject封装了MFC的基础的机制
    1.1 new和Delete
    1.2 Assert
    1.3 运行式信息
    1.4 动态创建
    1.5 序列化
  2 应用程序框架
    应用程序启动相关信息,以及MFC消息映射
    机制。
  3 窗口支持类
    封装了窗口操作的API,各种控件及窗口的
    框架.
  4 绘图类
    提供了绘图API的封装,以及相关的GDI设备
    封装.
  5 MFC的集合类
    提供了数组、链表、映射的数据结构的操作.
  6 数据库支持类
    ODBC支持类和DAO的支持类。
    DAO的类已作废.
  7 同步类
    临界区/事件/互斥/信号量的封装
  8 Socket类
    封装了socket的编程.
  9 常用数据结构
    CString CRect CPoint等.

五 第一个MFC程序

  1 环境设置
    1.1 修改头文件
    1.2 在Setting中增加MFC库支持
  2 增加应用程序类CWinApp
    2.1 添加CWinApp的子类CMyApp
    2.2 添加InitInstance函数
     是在程序启动过程中,会被调用,我们可以
     在这个函数中,创建窗口或者各种初始化
     操作.
    2.3 添加CMyApp的全局变量
  3 窗口
    3.1 添加CFrameWnd的子类CMyFrameWnd
    3.2 在App的InitInstance函数定义窗口
        对象
    3.3 创建窗口(Create)并显示(ShowWindow)
    3.4 将窗口设置成App的主窗口
        m_pMainWnd = pWnd;
    3.5 在CMyFrameWnd中添加窗口处理函数
        WindowProc,在WindowProc中处理消息
        
六 MFC应用程序的启动

  MFC应用程序与Win32程序一样,都需要程序
  的入口函数.
  
  1 CWinApp 
    应用程序类,封装了应用程序的相关信息,
    可以提供初始化 消息循环等处理.
    CWinApp的构造函数:
    1.1 将this指针保存到ThreadState中. 
          m_pCurrentWinThread = this
    1.2 将this指针保存到ModuleState中
          m_pCurrentWinApp = this
    1.3 各种的成员变量的初始化
    
  2 程序的入口函数
    2.1 WinMain函数,与Win32程序一致.
    2.2 在WinMain函数中,调用了AfxWinMain
       函数.
    2.3 AfxWinMain函数
      2.3.1 调用AfxWinInit初始化应用程序
      2.3.2 调用CWinApp的InitApplication
            初始MFC内部数据
      2.3.3 调用CWinThread的InitInstance
            函数做初始化操作
      2.3.4 调用CWinThread的Run函数进行
            消息循环
      2.3.5 调用AfxWinTerm函数做退出处理.
   
  3 程序的启动
    3.1 CWinApp在构造过程中, 将自己的this
      指针分别保存到全局变量中.
    3.2 在AfxWinMain执行中,首先从全局变量
      中将保存CWinApp的地址获取到.
    3.3 调用CWinApp的InitInstance函数,进行
      初始化.我们在InitInstance函数中,创建
      窗口等初始化操作.
    3.4 调用Run函数,进行消息循环.

七 窗口创建及窗口处理函数

  1 窗口创建
    1.1 窗口的参数初始化,包括窗口类.风格
        窗口处理函数等信息. 
        注意:
        将DefWindowProc注册成窗口处理函数.
    1.2 设置 创建HOOK (钩子) 
        当窗口创建的时候,调用这个HOOK函数.
        Wnd -> HOOK -> WndProc
    1.3 创建窗口
        CreateWindowEx
    1.4 卸载创建HOOK
        将HOOK程序从当前程序中移除
     
  2 HOOK(钩子)程序
    2.1 使用AfxGetAfxWndProc函数获取了
        一个WNDPROC函数指针, 也就是
        AfxWndProc(AfxWndProcBase)函数
        地址.
    2.2 将这个WNDPROC函数设置成当前窗口的
        处理函数
    2.3 将窗口句柄和窗口类的指针保存到
        MFC的映射数据中.(afxMapHWND函数)
        
  3 AfxWndProc(Base)窗口处理函数
    3.1 根据窗口句柄获取了相对应的窗口
      的CWnd *类型的指针,从映射数据中
      根据窗口句柄查找CWnd *指针.
      (afxMapHWND函数)
    3.2 调用AfxCallWndProc函数
    3.3 在AfxCallWndProc函数中,调用CWnd
      的WindowProc函数
    注意: 在MFC程序当中,所有窗口处理都是
      使用一个函数.
        
  4 窗口的创建及处理过程
    4.1 将DefWindowProc函数注册成当前
        窗口的处理函数
    4.2 设置钩子函数
    4.3 创建窗口,并执行钩子函数
    4.4 将窗口类指针和窗口句柄的对应关系
        保存.  
    4.5 在钩子函数将AfxWndProc(Base)函数
        设置当前窗口的窗口处理函数
    4.6 在AfxWndProc(Base)收到窗口消息,
        从窗口对应关系中,查询相应的窗
        口类指针.
    4.7 调用窗口类WindowProc函数处理消息

八 消息映射

  1 消息映射添加
    1.1 在FrameWnd添加消息宏定义
    		DECLARE_MESSAGE_MAP
    1.2 添加消息宏实现
    1.3 添加消息处理函数
    1.4 添加消息和处理函数的对应
  
  2 消息宏的实现
    2.1 数据类型
      2.1.1 AFX_MSGMAP_ENTRY 是用于保存
      消息ID与对应函数指针,及相关的信息
      struct AFX_MSGMAP_ENTRY
			{
				UINT nMessage; //消息ID
				UINT nCode;//通知代码
				UINT nID; //控件的ID
				UINT nLastID;//控件的ID范围的最后
				UINT nSig;//操作类型或pfn函数类型
				AFX_PMSG pfn;//消息处理函数的函数指针
			};
			2.1.2 AFX_MSGMAP 用于保存GetBaseMap
			 的函数地址及AFX_MSGMAP_ENTRY数组的
			 地址.
			struct AFX_MSGMAP
			{
      	const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
      	//函数指针
      	const AFX_MSGMAP_ENTRY* lpEntries;
      	//AFX_MSGMAP_ENTRY类型指针
      };

    2.2 代码
	  class CMsgFrame : public CFrameWnd  
  	{
	  private: 
			static const AFX_MSGMAP_ENTRY _messageEntries[]; 
		protected: 
			static AFX_DATA const AFX_MSGMAP messageMap; 
			static const AFX_MSGMAP* PASCAL _GetBaseMessageMap(); 
			virtual const AFX_MSGMAP* GetMessageMap() const; 
		}
    const AFX_MSGMAP* PASCAL CMsgFrame::_GetBaseMessageMap() 
		{ 
		    return &CFrameWnd::messageMap; 
		} 
		
		const AFX_MSGMAP* CMsgFrame::GetMessageMap() const 
		{ 
				return &CMsgFrame::messageMap; 
		} 
		
		AFX_COMDAT AFX_DATADEF const AFX_MSGMAP CMsgFrame::messageMap = 
		{		
		  	&CMsgFrame::_GetBaseMessageMap, 
		    &CMsgFrame::_messageEntries[0] 
		}; 
		
		AFX_COMDAT const AFX_MSGMAP_ENTRY CMsgFrame::_messageEntries[] = 
		{
			{ WM_PAINT, 0, 0, 0, AfxSig_lwl,(AFX_PMSG)(AFX_PMSGW)(LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM))&OnPaint },
			{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } 
		};